/**
 * UnitCode for the MasterController project
 * 
 * The control of this application is done via the Serial/USB port using the following synax:
 * #set*fan*speed
 * where speed is a value from 0 - 255
 * #set*led*brightness
 * where brightness is a value from 0 - 255
 * #set*red*brightness
 * where brightness is a value from 0 - 255
 * #set*green*brightness
 * where brightness is a value from 0 - 255
 * #set*blue*brightness
 * where brightness is a value from 0 - 255
 *
 * #get*led
 * will return the led brightness
 * #get*fan
 * will return the fanSpeed parameter
 * #get*site
 * will return the siteName parameter
 * #get*red
 * will return the red brightness#set*green
 * #get*green
 * will return the green brightness
 * #get*blue
 * will return the blue brightness
 * #get*temp
 * will return the value read from the tempPin
 *
 * TODO: handle common code, make functions
 * TODO: handle to long strings in print functions
 * TODO: calibrate sensor inpput?
 *
 * Author: Mikael Bertlin 2009-11-01
 *
 * Version: 0.1 BETA
 *
*/

#include <NewSoftSerial.h>

#define lcdCMD 0xFE
#define lcdCLEAR 0x01
#define lcdON 0x0C
#define lcdOFF 0x08
#define lcdSET 0x7C
#define lcd20 0x03
#define lcd2 0x06
#define lcdCursorOn 0x0D
#define lcdCursorOff 0x0C
#define lcd2ndLine 0xC0

//Globals
int pinFan = 5;
int pinLcd = 3;
int pinLed = 8;
int pinRed = 10;
int pinGreen = 11;
int pinBlue = 9;
int val = 0;

int PWMMax = 255;
int PWMMin = 0;

int newLedSpeed = 255;
int newFanSpeed = 0;
int newRedSpeed = 255;
int newGreenSpeed = 255;
int newBlueSpeed = 255;

int fanSpeed = 0; //0-255
int ledSpeed = 255; //0-255
int redSpeed = 255; //255-0
int greenSpeed = 255; //255-0
int blueSpeed = 255; //255-0

//Sensors
int tempPin = 5;
int sensorTemp = 0;
int sensorMin = 0;
int sensorMax = 1023;

//Check size of string if you change this name!
char siteName[9] = "Arduino2";
char buffer[20];
NewSoftSerial LCD(2, pinLcd); // serial LCD 

void clearLCD(){
  LCD.print(lcdCMD, BYTE);
  LCD.print(lcdCLEAR,BYTE);
}

void setup(){
  //For pin 11 and 3, 0x01 ---> 0x07
  //Changing the freq of the pwm
  //TCCR2B = TCCR2B & 0b11111000 | 0x03;
  
  pinMode(pinFan, OUTPUT);
  pinMode(pinLcd, OUTPUT);
  pinMode(pinLed, OUTPUT);
  pinMode(pinRed, OUTPUT);
  pinMode(pinGreen, OUTPUT);
  pinMode(pinBlue, OUTPUT);

  analogWrite(pinFan, fanSpeed);
  analogWrite(pinLed, ledSpeed);
  analogWrite(pinRed, redSpeed);
  analogWrite(pinGreen, greenSpeed);
  analogWrite(pinBlue, blueSpeed);
  digitalWrite(pinLcd, HIGH);

  LCD.begin(9600);
  Serial.begin(9600);  
  //Set LCD to 2x20 only needed once!
  LCD.print(lcdSET,BYTE);
  LCD.print(lcd20,BYTE);
  LCD.print(lcdSET,BYTE);
  LCD.print(lcd2,BYTE);
 
  clearLCD();
  LCD.print(lcdCMD, BYTE);
  LCD.print(lcdCursorOn,BYTE);
  delay(3000); 
  
  LCD.print("Site: ");
  LCD.print(siteName);
  delay(3000);
  
  clearLCD();
  LCD.print(siteName);
  LCD.print(" Ready ...");
  delay(3000);
}

void printLCDLine2(char str[20], int val){
   LCD.print(lcdCMD, BYTE);
   LCD.print(lcd2ndLine, BYTE);
   LCD.print("                    ");
   LCD.print(lcdCMD, BYTE);
   LCD.print(lcd2ndLine, BYTE);
   LCD.print(str);
   
   if(val > 0){
     LCD.print(val);
   }
}


void cmd(){
  static char myCmd[1024];
  char ch;
  static int i;
  while((ch = Serial.read()) != -1){
    //Break if buffer full
    if(i >= sizeof(myCmd))
      break;
    myCmd[i++] = ch;
    if(ch == '\n'){
      myCmd[i] = '\0';
      break;
    }
  }
 
  if(myCmd[i] == '\0' && i >= 8){
  //Handle cmd then reset buffer
  char* p = &myCmd[0];
  char* q;
  //Handle commands via the serial / usb port
  //Format: #Command*Sensor*value
  if(p[0] == '#'){
    p++;
    q = strstr(p, "*");
    q[0] = 0;
    if((strcmp(p, "set") == 0)){
      p = q;
      p++;
      q = strstr(p, "*");
      q[0] = 0;
      if((strcmp(p, "fan") == 0)){
        p = q;
        p++; 
        q = strstr(p, "\n");        
        q[0] = 0;
        int newSpeed = atoi(p);
        if((newSpeed >= PWMMin) && (newSpeed <= PWMMax)){
          fanSpeed = newSpeed;
          Serial.println(fanSpeed);
        } else {
          Serial.println(fanSpeed);
        }
      } else if((strcmp(p, "led") == 0)){
        p = q;
        p++; 
        q = strstr(p, "\n");        
        q[0] = 0;
        int newSpeed = atoi(p);
        if((newSpeed >= PWMMin) && (newSpeed <= PWMMax)){
          ledSpeed = newSpeed;
          Serial.println(ledSpeed);
        } else {
            Serial.println(ledSpeed);
        }
      } else if((strcmp(p, "red") == 0)){
        p = q;
        p++; 
        q = strstr(p, "\n");        
        q[0] = 0;
        int newSpeed = atoi(p);
        if((newSpeed >= PWMMin) && (newSpeed <= PWMMax)){
          redSpeed = newSpeed;
          Serial.println(redSpeed);
        } else {
          Serial.println(redSpeed);
        }
      } else if((strcmp(p, "green") == 0)){
        p = q;
        p++; 
        q = strstr(p, "\n");        
        q[0] = 0;
        int newSpeed = atoi(p);
        if((newSpeed >= PWMMin) && (newSpeed <= PWMMax)){
          greenSpeed = newSpeed;
          Serial.println(greenSpeed);
        } else {
          Serial.println(greenSpeed);
        }
      } else if((strcmp(p, "blue") == 0)){
        p = q;
        p++; 
        q = strstr(p, "\n");        
        q[0] = 0;
        int newSpeed = atoi(p);
        if((newSpeed >= PWMMin) && (newSpeed <= PWMMax)){
          blueSpeed = newSpeed;
          Serial.println(blueSpeed);
        } else {
          Serial.println(blueSpeed);
        }
      } else if((strcmp(p, "lcd") == 0)){
        p = q;
        p++; 
        q = strstr(p, "\n");        
        q[0] = 0;
        printLCDLine2(p,0);        
      } else {
        Serial.println("Not implemented!");
      }
    } else if(strcmp(p, "get") == 0){
      p = q;
      p++;
      q = strstr(p, "*");
      q[0] = 0;    
      if((strcmp(p, "fan") == 0)){
        Serial.println(fanSpeed);
      } else if((strcmp(p, "led") == 0)){
        Serial.println(ledSpeed);
      } else if((strcmp(p, "site") == 0)){
        Serial.println(siteName);
      } else if((strcmp(p, "temp") == 0)){
        Serial.println(sensorTemp);
      } else {
        Serial.println("Not implemented!");
      }
    } else {
      Serial.print(myCmd);
      Serial.println("Not implemented!");
    }
  }  
  //Clean up buffer
  memset(myCmd, 0, 1024);
  i = 0;
  }
}

void loop(){
  
  //TODO: do we need calibrate this? min and max?
   sensorTemp = analogRead(tempPin);
   sensorTemp = map(sensorTemp, sensorMin, sensorMax, 0, 200);
   sensorTemp = constrain(sensorTemp, 0, 200);
  
  delay(50);
  
  if(Serial.available()){
    //Need some time to fill the port buffer
    delay(100);
    cmd();
  } else {
    //Control the speed of the fan (PWM on a MOSFET)
    if(newFanSpeed != fanSpeed){
      //490Hz 0-255
      analogWrite(pinFan,fanSpeed);
      LCD.print(lcdCMD, BYTE);
      LCD.print(lcd2ndLine, BYTE);
      
      newFanSpeed = fanSpeed;
      printLCDLine2("Fan: ", fanSpeed);
    }
    //Control the brightness of the led (PWM)
    if(newLedSpeed != ledSpeed){
      //490Hz 0-255
      analogWrite(pinLed,ledSpeed);
      newLedSpeed = ledSpeed;
      printLCDLine2("LED: ", ledSpeed);
    }
    if(newRedSpeed != redSpeed){
      //490Hz 0-255
      analogWrite(pinRed,redSpeed);
      newRedSpeed = redSpeed;
      printLCDLine2("Red: ", redSpeed);
    }
    if(newBlueSpeed != blueSpeed){
      //490Hz 0-255
      analogWrite(pinBlue,blueSpeed);
      newBlueSpeed = blueSpeed;
      printLCDLine2("Blue: ", blueSpeed);
    }
    if(newGreenSpeed != greenSpeed){
      //490Hz 0-255
      analogWrite(pinGreen,greenSpeed);
      newGreenSpeed = greenSpeed;
      printLCDLine2("Green: ", greenSpeed);
    }
  }
}
